/*
 * @Descripttion: 
 * @version: 1.0
 * @Author: yuqy
 * @Date: 2021-03-07 17:08:23
 * @LastEditors: yuqy
 * @LastEditTime: 2023-11-02 11:26:15
 * @model: -
 */
//通过class获取元素
const getClass = (cls) => {
	var ret = [];
	var els = document.getElementsByTagName("*");
	for (var i = 0; i < els.length; i++) {
		//判断els[i]中是否存在cls这个className;.indexOf("cls")判断cls存在的下标，如果下标>=0则存在;
		if (els[i].className === cls || els[i].className.indexOf("cls") >= 0 || els[i].className.indexOf(" cls") >= 0 || els[i].className.indexOf(" cls ") > 0) {
			ret.push(els[i]);
		}
	}
	return ret;
}

const getStyle = (obj, attr) => {//解决JS兼容问题获取正确的属性值
	return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, false)[attr];
}

/**
 * @name: 阻止默认事件 和事件冒泡
 * @msg: 
 * @return {*}
 */
const stopPreventFn = (event) => {
	let e = event || window.event
	e.preventDefault() // 阻止默认事件
	e.stopPropagation() // 阻止事件冒泡
	return e;
}


// html结构
/* <div class="move_wrap" id="upload_list_wrap">
	占位结构用于撑开位置
	<ul class="list_wrap placeholder_wrap" >
		<li style="opacity: 0;" v-for="(item,index) in listData" :key="index + 1000" /> 
	</ul>
	拖动结构
	<ul class="list_wrap list_move_wrap" >
		<li v-for="(item,index) in listData" :key="index" @click.stop="delListTest"></li>
	</ul>
</div> */
// 参考基础样式
// .move_wrap {
//   border: 10px solid #fff;
//   position: relative;
//   padding-top: 0;
// }
// .placeholder_wrap {
//   overflow: hidden;
// }
// .list_wrap {
//   background: blue;
//   position: relative;
//   z-index: 9;
// }
// .list_wrap> li {
//   width: 300px;
//   height: 200px;
//   border: 10px solid red;
//   float: left;
//   margin:0 10px 10px 0;
// }

// .list_move_wrap {
//   position: absolute;
//   width: 100%;
//   height: 100%;
//   top: 0;
//   left: 0;
//   z-index: 99;
//   li {
//     background: #333;
//     &.active {
//       border-color: green;
//     }
//     &.moveActive {
//       border-color: yellow;
//     }
//     span {
//       cursor: pointer;
//     }
//   }
// }
// 组件调用
// // 实例化拖动事件
// let moveEl = new MoveFn({ name: '测试拖动', el: id, callBack, moveStart, moveEnd });
// moveEl.init();
/**
 * @name: 
 * @msg: 
 * @param {*} name 实例化对象名称
 * @param {*} el 实例化对象的容器
 * @param {*} callBack 拖动替换成功后的回调
 * @param {*} moveStart 
 * @param {*} moveEnd
 * @return {*}
 */
export function MoveFn({ name, el, callBack, moveStart, moveEnd }){
	//需要移动的元素
	let aLi = [];
	//获取同级别占位框的位置
	let aLiP = [];
	let minZindex = 10;
	let disX = 0;
	let disY = 0;
	let aPos = [];
	let moveEl = 'list_move_wrap li';
	let placeEl = 'placeholder_wrap li';
	this.name =  name;
	this.el = el; // 拖动的容器
	this.moveEl = moveEl; // 拖动的元素
	this.placeEl = placeEl;// 占位元素
	this.minZindex = minZindex; // 显示的层级
	this.isMoving = false; // 当前是否在拖动
	this.init = () => { 
		//需要移动的元素
		aLi = document.querySelectorAll(`#${el} .${moveEl}`);
		//获取同级别占位框的位置
		aLiP = document.querySelectorAll(`#${el} .${placeEl}`);
		aLi.forEach((s, i) => {
			let t = s.offsetTop; // 初始位置
			let l = s.offsetLeft; //初始位置
			if (aLiP[i]) {
				t = aLiP[i].offsetTop;
				l = aLiP[i].offsetLeft;
			}
			s.style.top = t + "px";
			s.style.left = l + "px";
			s.style.zIndex = minZindex;
			aPos[i] = { left: l, top: t };
			s.index = i;
			s.style.position = "absolute";
			s.style.margin = 0;
			this.setDrag(s);
		})
	}
	// 拖动事件
	this.setDrag = (obj) => {
		obj.onmouseover = null;
		obj.onmousedown = null;
		obj.ontouchstart = null;
		obj.onmouseover = () => {
			obj.style.cursor = "move";
		}
		// touch点击开始
		obj.ontouchstart = (event) => {
			let e = stopPreventFn(event);
			if (e.changedTouches.length <= 0) return;
			let clientX = e.changedTouches[0].clientX;
			let clientY = e.changedTouches[0].clientY;
			let { disX, disY, scrollTop, scrollLeft } = this.mouseTouchStart(clientX, clientY, obj);
			document.ontouchmove = (event) => {
				e = stopPreventFn(event);
				clientX = e.changedTouches[0].clientX;
				clientY = e.changedTouches[0].clientY;
				let l = clientX - disX + scrollLeft;
				let t = clientY - disY + scrollTop;
				this.mouseTouchMove(l, t, obj);
			}
			// 滑动结束
			document.ontouchend = (event) => {
				e = stopPreventFn(event);
				document.ontouchmove = null;//当鼠标弹起时移出移动事件
				document.ontouchend = null;//移出up事件，清空内存
				this.mouseTouchEnd(obj);
			}
			clearInterval(obj.timer);
		}
		// 鼠标点击开始
		obj.onmousedown = (event) => {
			let e = stopPreventFn(event);
			//当鼠标按下时计算鼠标与拖拽对象的距离
			let { disX, disY, scrollTop, scrollLeft } = this.mouseTouchStart(e.clientX, e.clientY, obj);
			document.onmousemove = (event) => {
				e = stopPreventFn(event);
				//当鼠标拖动时计算div的位置
				let l = e.clientX - disX + scrollLeft;
				let t = e.clientY - disY + scrollTop;
				this.mouseTouchMove(l, t, obj);
			}
			document.onmouseup = (event) => {
				e = stopPreventFn(event);
				document.onmousemove = null;//当鼠标弹起时移出移动事件
				document.onmouseup = null;//移出up事件，清空内存
				this.mouseTouchEnd(obj);
			}
			clearInterval(obj.timer);
			return false;//低版本出现禁止符号
		}
	} 

	//  鼠标或者手势开始点击
	this.mouseTouchStart = (clientX, clientY, obj) => {
		var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
		var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
		obj.style.zIndex = minZindex * 100;
		disX = clientX + scrollLeft - obj.offsetLeft;
		disY = clientY + scrollTop - obj.offsetTop;
		return { 
			disX, disY, scrollTop, scrollLeft
		}
	}
	// 鼠标或者手指开始移动
	this.mouseTouchMove = (l, t, obj) => {
		obj.style.left = l + "px";
	   	obj.style.top = t + "px";
	   	for (var i = 0; i < aLi.length; i++) {
		   aLi[i].className = "";
	   	}
	   	let oNear = findMin(obj, aLi);
	   	if (oNear) {
		   oNear.className = "active";
	   	}
		obj.className = "moveActive";
		this.isMoving = true;   
	   	moveStart && moveStart();
	}
	// 鼠标或者手指移动结束
	this.mouseTouchEnd = (obj) => {
		//检测是否普碰上，在交换位置
		var oNear = findMin(obj);
		if (oNear) {
			oNear.className = "";
			oNear.style.zIndex = minZindex * 10;
			this.startMove(oNear, aPos[obj.index]);
			this.startMove(obj, aPos[oNear.index], moveEnd);
			//交换index
			oNear.index += obj.index;
			obj.index = oNear.index - obj.index;
			oNear.index = oNear.index - obj.index;
			if (callBack) {
				callBack(oNear.index, obj.index);
			}
		} else {
			// 我是初始位置
			this.startMove(obj, aPos[obj.index], moveEnd);
		}
	}

	// 组件移动
	this.startMove = (obj, aPosObj, fun) => {
		clearInterval(obj.timer);
		obj.timer = setInterval(() => {
			var isStop = true;
			for (var attr in aPosObj) {
				var iCur = 0;
				//判断运动的是不是透明度值
				if (attr == "opacity") {
					iCur = parseInt(parseFloat(getStyle(obj, attr)) * 100);
				} else {
					iCur = parseInt(getStyle(obj, attr));
				}
				var ispeed = (aPosObj[attr] - iCur) / 2;
				//运动速度如果大于0则向下取整，如果小于0想上取整；
				ispeed = ispeed > 0 ? Math.ceil(ispeed) : Math.floor(ispeed);
				//判断所有运动是否全部完成
				if (iCur != aPosObj[attr]) {
					isStop = false;
				}
				//运动开始
				if (attr == "opacity") {
					obj.style.filter = "alpha:(opacity:" + (aPosObj[attr] + ispeed) + ")";
					obj.style.opacity = (aPosObj[attr] + ispeed) / 100;
				} else {
					obj.style[attr] = iCur + ispeed + "px";
				}
			}
			//判断是否全部完成
			if (isStop) {
				obj.className = '';
				obj.style.zIndex = minZindex;
				this.isMoving = false;  
				clearInterval(obj.timer);
				if (fun) {
					fun();
				}
			}
		}, 30);
	}

	//碰撞检测
	function colTest(obj1, obj2) {
		var t1 = obj1.offsetTop;
		var r1 = obj1.offsetWidth + obj1.offsetLeft;
		var b1 = obj1.offsetHeight + obj1.offsetTop;
		var l1 = obj1.offsetLeft;
		var t2 = obj2.offsetTop;
		var r2 = obj2.offsetWidth + obj2.offsetLeft;
		var b2 = obj2.offsetHeight + obj2.offsetTop;
		var l2 = obj2.offsetLeft;
		if (t1 > b2 || r1 < l2 || b1 < t2 || l1 > r2) {
			return false;
		} else {
			return true;
		}
	}

	//勾股定理求距离
	function getDis(obj1, obj2) {
		var a = obj1.offsetLeft - obj2.offsetLeft;
		var b = obj1.offsetTop - obj2.offsetTop;
		return Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
	}

	//找到距离最近的
	function findMin(obj) {
		var minDis = 999999999;
		var minIndex = -1;
		for (var i = 0; i < aLi.length; i++) {
			if (obj == aLi[i]) continue;
			if (colTest(obj, aLi[i])) {
				var dis = getDis(obj, aLi[i]);
				if (dis < minDis) {
					minDis = dis;
					minIndex = i;
				}
			}
		}
		if (minIndex == -1) {
			return null;
		} else {
			return aLi[minIndex];
		}
	}
}
